home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-desktop-9.10-i386-PL.iso / casper / filesystem.squashfs / usr / lib / python2.6 / modulefinder.py < prev    next >
Text File  |  2009-11-02  |  24KB  |  672 lines

  1. """Find modules used by a script, using introspection."""
  2. # This module should be kept compatible with Python 2.2, see PEP 291.
  3.  
  4. from __future__ import generators
  5. import dis
  6. import imp
  7. import marshal
  8. import os
  9. import sys
  10. import types
  11. import struct
  12.  
  13. if hasattr(sys.__stdout__, "newlines"):
  14.     READ_MODE = "U"  # universal line endings
  15. else:
  16.     # remain compatible with Python  < 2.3
  17.     READ_MODE = "r"
  18.  
  19. LOAD_CONST = chr(dis.opname.index('LOAD_CONST'))
  20. IMPORT_NAME = chr(dis.opname.index('IMPORT_NAME'))
  21. STORE_NAME = chr(dis.opname.index('STORE_NAME'))
  22. STORE_GLOBAL = chr(dis.opname.index('STORE_GLOBAL'))
  23. STORE_OPS = [STORE_NAME, STORE_GLOBAL]
  24. HAVE_ARGUMENT = chr(dis.HAVE_ARGUMENT)
  25.  
  26. # Modulefinder does a good job at simulating Python's, but it can not
  27. # handle __path__ modifications packages make at runtime.  Therefore there
  28. # is a mechanism whereby you can register extra paths in this map for a
  29. # package, and it will be honored.
  30.  
  31. # Note this is a mapping is lists of paths.
  32. packagePathMap = {}
  33.  
  34. # A Public interface
  35. def AddPackagePath(packagename, path):
  36.     paths = packagePathMap.get(packagename, [])
  37.     paths.append(path)
  38.     packagePathMap[packagename] = paths
  39.  
  40. replacePackageMap = {}
  41.  
  42. # This ReplacePackage mechanism allows modulefinder to work around the
  43. # way the _xmlplus package injects itself under the name "xml" into
  44. # sys.modules at runtime by calling ReplacePackage("_xmlplus", "xml")
  45. # before running ModuleFinder.
  46.  
  47. def ReplacePackage(oldname, newname):
  48.     replacePackageMap[oldname] = newname
  49.  
  50.  
  51. class Module:
  52.  
  53.     def __init__(self, name, file=None, path=None):
  54.         self.__name__ = name
  55.         self.__file__ = file
  56.         self.__path__ = path
  57.         self.__code__ = None
  58.         # The set of global names that are assigned to in the module.
  59.         # This includes those names imported through starimports of
  60.         # Python modules.
  61.         self.globalnames = {}
  62.         # The set of starimports this module did that could not be
  63.         # resolved, ie. a starimport from a non-Python module.
  64.         self.starimports = {}
  65.  
  66.     def __repr__(self):
  67.         s = "Module(%r" % (self.__name__,)
  68.         if self.__file__ is not None:
  69.             s = s + ", %r" % (self.__file__,)
  70.         if self.__path__ is not None:
  71.             s = s + ", %r" % (self.__path__,)
  72.         s = s + ")"
  73.         return s
  74.  
  75. class ModuleFinder:
  76.  
  77.     def __init__(self, path=None, debug=0, excludes=[], replace_paths=[]):
  78.         if path is None:
  79.             path = sys.path
  80.         self.path = path
  81.         self.modules = {}
  82.         self.badmodules = {}
  83.         self.debug = debug
  84.         self.indent = 0
  85.         self.excludes = excludes
  86.         self.replace_paths = replace_paths
  87.         self.processed_paths = []   # Used in debugging only
  88.  
  89.     def msg(self, level, str, *args):
  90.         if level <= self.debug:
  91.             for i in range(self.indent):
  92.                 print "   ",
  93.             print str,
  94.             for arg in args:
  95.                 print repr(arg),
  96.             print
  97.  
  98.     def msgin(self, *args):
  99.         level = args[0]
  100.         if level <= self.debug:
  101.             self.indent = self.indent + 1
  102.             self.msg(*args)
  103.  
  104.     def msgout(self, *args):
  105.         level = args[0]
  106.         if level <= self.debug:
  107.             self.indent = self.indent - 1
  108.             self.msg(*args)
  109.  
  110.     def run_script(self, pathname):
  111.         self.msg(2, "run_script", pathname)
  112.         fp = open(pathname, READ_MODE)
  113.         stuff = ("", "r", imp.PY_SOURCE)
  114.         self.load_module('__main__', fp, pathname, stuff)
  115.  
  116.     def load_file(self, pathname):
  117.         dir, name = os.path.split(pathname)
  118.         name, ext = os.path.splitext(name)
  119.         fp = open(pathname, READ_MODE)
  120.         stuff = (ext, "r", imp.PY_SOURCE)
  121.         self.load_module(name, fp, pathname, stuff)
  122.  
  123.     def import_hook(self, name, caller=None, fromlist=None, level=-1):
  124.         self.msg(3, "import_hook", name, caller, fromlist, level)
  125.         parent = self.determine_parent(caller, level=level)
  126.         q, tail = self.find_head_package(parent, name)
  127.         m = self.load_tail(q, tail)
  128.         if not fromlist:
  129.             return q
  130.         if m.__path__:
  131.             self.ensure_fromlist(m, fromlist)
  132.         return None
  133.  
  134.     def determine_parent(self, caller, level=-1):
  135.         self.msgin(4, "determine_parent", caller, level)
  136.         if not caller or level == 0:
  137.             self.msgout(4, "determine_parent -> None")
  138.             return None
  139.         pname = caller.__name__
  140.         if level >= 1: # relative import
  141.             if caller.__path__:
  142.                 level -= 1
  143.             if level == 0:
  144.                 parent = self.modules[pname]
  145.                 assert parent is caller
  146.                 self.msgout(4, "determine_parent ->", parent)
  147.                 return parent
  148.             if pname.count(".") < level:
  149.                 raise ImportError, "relative importpath too deep"
  150.             pname = ".".join(pname.split(".")[:-level])
  151.             parent = self.modules[pname]
  152.             self.msgout(4, "determine_parent ->", parent)
  153.             return parent
  154.         if caller.__path__:
  155.             parent = self.modules[pname]
  156.             assert caller is parent
  157.             self.msgout(4, "determine_parent ->", parent)
  158.             return parent
  159.         if '.' in pname:
  160.             i = pname.rfind('.')
  161.             pname = pname[:i]
  162.             parent = self.modules[pname]
  163.             assert parent.__name__ == pname
  164.             self.msgout(4, "determine_parent ->", parent)
  165.             return parent
  166.         self.msgout(4, "determine_parent -> None")
  167.         return None
  168.  
  169.     def find_head_package(self, parent, name):
  170.         self.msgin(4, "find_head_package", parent, name)
  171.         if '.' in name:
  172.             i = name.find('.')
  173.             head = name[:i]
  174.             tail = name[i+1:]
  175.         else:
  176.             head = name
  177.             tail = ""
  178.         if parent:
  179.             qname = "%s.%s" % (parent.__name__, head)
  180.         else:
  181.             qname = head
  182.         q = self.import_module(head, qname, parent)
  183.         if q:
  184.             self.msgout(4, "find_head_package ->", (q, tail))
  185.             return q, tail
  186.         if parent:
  187.             qname = head
  188.             parent = None
  189.             q = self.import_module(head, qname, parent)
  190.             if q:
  191.                 self.msgout(4, "find_head_package ->", (q, tail))
  192.                 return q, tail
  193.         self.msgout(4, "raise ImportError: No module named", qname)
  194.         raise ImportError, "No module named " + qname
  195.  
  196.     def load_tail(self, q, tail):
  197.         self.msgin(4, "load_tail", q, tail)
  198.         m = q
  199.         while tail:
  200.             i = tail.find('.')
  201.             if i < 0: i = len(tail)
  202.             head, tail = tail[:i], tail[i+1:]
  203.             mname = "%s.%s" % (m.__name__, head)
  204.             m = self.import_module(head, mname, m)
  205.             if not m:
  206.                 self.msgout(4, "raise ImportError: No module named", mname)
  207.                 raise ImportError, "No module named " + mname
  208.         self.msgout(4, "load_tail ->", m)
  209.         return m
  210.  
  211.     def ensure_fromlist(self, m, fromlist, recursive=0):
  212.         self.msg(4, "ensure_fromlist", m, fromlist, recursive)
  213.         for sub in fromlist:
  214.             if sub == "*":
  215.                 if not recursive:
  216.                     all = self.find_all_submodules(m)
  217.                     if all:
  218.                         self.ensure_fromlist(m, all, 1)
  219.             elif not hasattr(m, sub):
  220.                 subname = "%s.%s" % (m.__name__, sub)
  221.                 submod = self.import_module(sub, subname, m)
  222.                 if not submod:
  223.                     raise ImportError, "No module named " + subname
  224.  
  225.     def find_all_submodules(self, m):
  226.         if not m.__path__:
  227.             return
  228.         modules = {}
  229.         # 'suffixes' used to be a list hardcoded to [".py", ".pyc", ".pyo"].
  230.         # But we must also collect Python extension modules - although
  231.         # we cannot separate normal dlls from Python extensions.
  232.         suffixes = []
  233.         for triple in imp.get_suffixes():
  234.             suffixes.append(triple[0])
  235.         for dir in m.__path__:
  236.             try:
  237.                 names = os.listdir(dir)
  238.             except os.error:
  239.                 self.msg(2, "can't list directory", dir)
  240.                 continue
  241.             for name in names:
  242.                 mod = None
  243.                 for suff in suffixes:
  244.                     n = len(suff)
  245.                     if name[-n:] == suff:
  246.                         mod = name[:-n]
  247.                         break
  248.                 if mod and mod != "__init__":
  249.                     modules[mod] = mod
  250.         return modules.keys()
  251.  
  252.     def import_module(self, partname, fqname, parent):
  253.         self.msgin(3, "import_module", partname, fqname, parent)
  254.         try:
  255.             m = self.modules[fqname]
  256.         except KeyError:
  257.             pass
  258.         else:
  259.             self.msgout(3, "import_module ->", m)
  260.             return m
  261.         if fqname in self.badmodules:
  262.             self.msgout(3, "import_module -> None")
  263.             return None
  264.         if parent and parent.__path__ is None:
  265.             self.msgout(3, "import_module -> None")
  266.             return None
  267.         try:
  268.             fp, pathname, stuff = self.find_module(partname,
  269.                                                    parent and parent.__path__, parent)
  270.         except ImportError:
  271.             self.msgout(3, "import_module ->", None)
  272.             return None
  273.         try:
  274.             m = self.load_module(fqname, fp, pathname, stuff)
  275.         finally:
  276.             if fp: fp.close()
  277.         if parent:
  278.             setattr(parent, partname, m)
  279.         self.msgout(3, "import_module ->", m)
  280.         return m
  281.  
  282.     def load_module(self, fqname, fp, pathname, file_info):
  283.         suffix, mode, type = file_info
  284.         self.msgin(2, "load_module", fqname, fp and "fp", pathname)
  285.         if type == imp.PKG_DIRECTORY:
  286.             m = self.load_package(fqname, pathname)
  287.             self.msgout(2, "load_module ->", m)
  288.             return m
  289.         if type == imp.PY_SOURCE:
  290.             co = compile(fp.read()+'\n', pathname, 'exec')
  291.         elif type == imp.PY_COMPILED:
  292.             if fp.read(4) != imp.get_magic():
  293.                 self.msgout(2, "raise ImportError: Bad magic number", pathname)
  294.                 raise ImportError, "Bad magic number in %s" % pathname
  295.             fp.read(4)
  296.             co = marshal.load(fp)
  297.         else:
  298.             co = None
  299.         m = self.add_module(fqname)
  300.         m.__file__ = pathname
  301.         if co:
  302.             if self.replace_paths:
  303.                 co = self.replace_paths_in_code(co)
  304.             m.__code__ = co
  305.             self.scan_code(co, m)
  306.         self.msgout(2, "load_module ->", m)
  307.         return m
  308.  
  309.     def _add_badmodule(self, name, caller):
  310.         if name not in self.badmodules:
  311.             self.badmodules[name] = {}
  312.         if caller:
  313.             self.badmodules[name][caller.__name__] = 1
  314.         else:
  315.             self.badmodules[name]["-"] = 1
  316.  
  317.     def _safe_import_hook(self, name, caller, fromlist, level=-1):
  318.         # wrapper for self.import_hook() that won't raise ImportError
  319.         if name in self.badmodules:
  320.             self._add_badmodule(name, caller)
  321.             return
  322.         try:
  323.             self.import_hook(name, caller, level=level)
  324.         except ImportError, msg:
  325.             self.msg(2, "ImportError:", str(msg))
  326.             self._add_badmodule(name, caller)
  327.         else:
  328.             if fromlist:
  329.                 for sub in fromlist:
  330.                     if sub in self.badmodules:
  331.                         self._add_badmodule(sub, caller)
  332.                         continue
  333.                     try:
  334.                         self.import_hook(name, caller, [sub], level=level)
  335.                     except ImportError, msg:
  336.                         self.msg(2, "ImportError:", str(msg))
  337.                         fullname = name + "." + sub
  338.                         self._add_badmodule(fullname, caller)
  339.  
  340.     def scan_opcodes(self, co,
  341.                      unpack = struct.unpack):
  342.         # Scan the code, and yield 'interesting' opcode combinations
  343.         # Version for Python 2.4 and older
  344.         code = co.co_code
  345.         names = co.co_names
  346.         consts = co.co_consts
  347.         while code:
  348.             c = code[0]
  349.             if c in STORE_OPS:
  350.                 oparg, = unpack('<H', code[1:3])
  351.                 yield "store", (names[oparg],)
  352.                 code = code[3:]
  353.                 continue
  354.             if c == LOAD_CONST and code[3] == IMPORT_NAME:
  355.                 oparg_1, oparg_2 = unpack('<xHxH', code[:6])
  356.                 yield "import", (consts[oparg_1], names[oparg_2])
  357.                 code = code[6:]
  358.                 continue
  359.             if c >= HAVE_ARGUMENT:
  360.                 code = code[3:]
  361.             else:
  362.                 code = code[1:]
  363.  
  364.     def scan_opcodes_25(self, co,
  365.                      unpack = struct.unpack):
  366.         # Scan the code, and yield 'interesting' opcode combinations
  367.         # Python 2.5 version (has absolute and relative imports)
  368.         code = co.co_code
  369.         names = co.co_names
  370.         consts = co.co_consts
  371.         LOAD_LOAD_AND_IMPORT = LOAD_CONST + LOAD_CONST + IMPORT_NAME
  372.         while code:
  373.             c = code[0]
  374.             if c in STORE_OPS:
  375.                 oparg, = unpack('<H', code[1:3])
  376.                 yield "store", (names[oparg],)
  377.                 code = code[3:]
  378.                 continue
  379.             if code[:9:3] == LOAD_LOAD_AND_IMPORT:
  380.                 oparg_1, oparg_2, oparg_3 = unpack('<xHxHxH', code[:9])
  381.                 level = consts[oparg_1]
  382.                 if level == -1: # normal import
  383.                     yield "import", (consts[oparg_2], names[oparg_3])
  384.                 elif level == 0: # absolute import
  385.                     yield "absolute_import", (consts[oparg_2], names[oparg_3])
  386.                 else: # relative import
  387.                     yield "relative_import", (level, consts[oparg_2], names[oparg_3])
  388.                 code = code[9:]
  389.                 continue
  390.             if c >= HAVE_ARGUMENT:
  391.                 code = code[3:]
  392.             else:
  393.                 code = code[1:]
  394.  
  395.     def scan_code(self, co, m):
  396.         code = co.co_code
  397.         if sys.version_info >= (2, 5):
  398.             scanner = self.scan_opcodes_25
  399.         else:
  400.             scanner = self.scan_opcodes
  401.         for what, args in scanner(co):
  402.             if what == "store":
  403.                 name, = args
  404.                 m.globalnames[name] = 1
  405.             elif what in ("import", "absolute_import"):
  406.                 fromlist, name = args
  407.                 have_star = 0
  408.                 if fromlist is not None:
  409.                     if "*" in fromlist:
  410.                         have_star = 1
  411.                     fromlist = [f for f in fromlist if f != "*"]
  412.                 if what == "absolute_import": level = 0
  413.                 else: level = -1
  414.                 self._safe_import_hook(name, m, fromlist, level=level)
  415.                 if have_star:
  416.                     # We've encountered an "import *". If it is a Python module,
  417.                     # the code has already been parsed and we can suck out the
  418.                     # global names.
  419.                     mm = None
  420.                     if m.__path__:
  421.                         # At this point we don't know whether 'name' is a
  422.                         # submodule of 'm' or a global module. Let's just try
  423.                         # the full name first.
  424.                         mm = self.modules.get(m.__name__ + "." + name)
  425.                     if mm is None:
  426.                         mm = self.modules.get(name)
  427.                     if mm is not None:
  428.                         m.globalnames.update(mm.globalnames)
  429.                         m.starimports.update(mm.starimports)
  430.                         if mm.__code__ is None:
  431.                             m.starimports[name] = 1
  432.                     else:
  433.                         m.starimports[name] = 1
  434.             elif what == "relative_import":
  435.                 level, fromlist, name = args
  436.                 if name:
  437.                     self._safe_import_hook(name, m, fromlist, level=level)
  438.                 else:
  439.                     parent = self.determine_parent(m, level=level)
  440.                     self._safe_import_hook(parent.__name__, None, fromlist, level=0)
  441.             else:
  442.                 # We don't expect anything else from the generator.
  443.                 raise RuntimeError(what)
  444.  
  445.         for c in co.co_consts:
  446.             if isinstance(c, type(co)):
  447.                 self.scan_code(c, m)
  448.  
  449.     def load_package(self, fqname, pathname):
  450.         self.msgin(2, "load_package", fqname, pathname)
  451.         newname = replacePackageMap.get(fqname)
  452.         if newname:
  453.             fqname = newname
  454.         m = self.add_module(fqname)
  455.         m.__file__ = pathname
  456.         m.__path__ = [pathname]
  457.  
  458.         # As per comment at top of file, simulate runtime __path__ additions.
  459.         m.__path__ = m.__path__ + packagePathMap.get(fqname, [])
  460.  
  461.         fp, buf, stuff = self.find_module("__init__", m.__path__)
  462.         self.load_module(fqname, fp, buf, stuff)
  463.         self.msgout(2, "load_package ->", m)
  464.         return m
  465.  
  466.     def add_module(self, fqname):
  467.         if fqname in self.modules:
  468.             return self.modules[fqname]
  469.         self.modules[fqname] = m = Module(fqname)
  470.         return m
  471.  
  472.     def find_module(self, name, path, parent=None):
  473.         if parent is not None:
  474.             # assert path is not None
  475.             fullname = parent.__name__+'.'+name
  476.         else:
  477.             fullname = name
  478.         if fullname in self.excludes:
  479.             self.msgout(3, "find_module -> Excluded", fullname)
  480.             raise ImportError, name
  481.  
  482.         if path is None:
  483.             if name in sys.builtin_module_names:
  484.                 return (None, None, ("", "", imp.C_BUILTIN))
  485.  
  486.             path = self.path
  487.         return imp.find_module(name, path)
  488.  
  489.     def report(self):
  490.         """Print a report to stdout, listing the found modules with their
  491.         paths, as well as modules that are missing, or seem to be missing.
  492.         """
  493.         print
  494.         print "  %-25s %s" % ("Name", "File")
  495.         print "  %-25s %s" % ("----", "----")
  496.         # Print modules found
  497.         keys = self.modules.keys()
  498.         keys.sort()
  499.         for key in keys:
  500.             m = self.modules[key]
  501.             if m.__path__:
  502.                 print "P",
  503.             else:
  504.                 print "m",
  505.             print "%-25s" % key, m.__file__ or ""
  506.  
  507.         # Print missing modules
  508.         missing, maybe = self.any_missing_maybe()
  509.         if missing:
  510.             print
  511.             print "Missing modules:"
  512.             for name in missing:
  513.                 mods = self.badmodules[name].keys()
  514.                 mods.sort()
  515.                 print "?", name, "imported from", ', '.join(mods)
  516.         # Print modules that may be missing, but then again, maybe not...
  517.         if maybe:
  518.             print
  519.             print "Submodules thay appear to be missing, but could also be",
  520.             print "global names in the parent package:"
  521.             for name in maybe:
  522.                 mods = self.badmodules[name].keys()
  523.                 mods.sort()
  524.                 print "?", name, "imported from", ', '.join(mods)
  525.  
  526.     def any_missing(self):
  527.         """Return a list of modules that appear to be missing. Use
  528.         any_missing_maybe() if you want to know which modules are
  529.         certain to be missing, and which *may* be missing.
  530.         """
  531.         missing, maybe = self.any_missing_maybe()
  532.         return missing + maybe
  533.  
  534.     def any_missing_maybe(self):
  535.         """Return two lists, one with modules that are certainly missing
  536.         and one with modules that *may* be missing. The latter names could
  537.         either be submodules *or* just global names in the package.
  538.  
  539.         The reason it can't always be determined is that it's impossible to
  540.         tell which names are imported when "from module import *" is done
  541.         with an extension module, short of actually importing it.
  542.         """
  543.         missing = []
  544.         maybe = []
  545.         for name in self.badmodules:
  546.             if name in self.excludes:
  547.                 continue
  548.             i = name.rfind(".")
  549.             if i < 0:
  550.                 missing.append(name)
  551.                 continue
  552.             subname = name[i+1:]
  553.             pkgname = name[:i]
  554.             pkg = self.modules.get(pkgname)
  555.             if pkg is not None:
  556.                 if pkgname in self.badmodules[name]:
  557.                     # The package tried to import this module itself and
  558.                     # failed. It's definitely missing.
  559.                     missing.append(name)
  560.                 elif subname in pkg.globalnames:
  561.                     # It's a global in the package: definitely not missing.
  562.                     pass
  563.                 elif pkg.starimports:
  564.                     # It could be missing, but the package did an "import *"
  565.                     # from a non-Python module, so we simply can't be sure.
  566.                     maybe.append(name)
  567.                 else:
  568.                     # It's not a global in the package, the package didn't
  569.                     # do funny star imports, it's very likely to be missing.
  570.                     # The symbol could be inserted into the package from the
  571.                     # outside, but since that's not good style we simply list
  572.                     # it missing.
  573.                     missing.append(name)
  574.             else:
  575.                 missing.append(name)
  576.         missing.sort()
  577.         maybe.sort()
  578.         return missing, maybe
  579.  
  580.     def replace_paths_in_code(self, co):
  581.         new_filename = original_filename = os.path.normpath(co.co_filename)
  582.         for f, r in self.replace_paths:
  583.             if original_filename.startswith(f):
  584.                 new_filename = r + original_filename[len(f):]
  585.                 break
  586.  
  587.         if self.debug and original_filename not in self.processed_paths:
  588.             if new_filename != original_filename:
  589.                 self.msgout(2, "co_filename %r changed to %r" \
  590.                                     % (original_filename,new_filename,))
  591.             else:
  592.                 self.msgout(2, "co_filename %r remains unchanged" \
  593.                                     % (original_filename,))
  594.             self.processed_paths.append(original_filename)
  595.  
  596.         consts = list(co.co_consts)
  597.         for i in range(len(consts)):
  598.             if isinstance(consts[i], type(co)):
  599.                 consts[i] = self.replace_paths_in_code(consts[i])
  600.  
  601.         return types.CodeType(co.co_argcount, co.co_nlocals, co.co_stacksize,
  602.                          co.co_flags, co.co_code, tuple(consts), co.co_names,
  603.                          co.co_varnames, new_filename, co.co_name,
  604.                          co.co_firstlineno, co.co_lnotab,
  605.                          co.co_freevars, co.co_cellvars)
  606.  
  607.  
  608. def test():
  609.     # Parse command line
  610.     import getopt
  611.     try:
  612.         opts, args = getopt.getopt(sys.argv[1:], "dmp:qx:")
  613.     except getopt.error, msg:
  614.         print msg
  615.         return
  616.  
  617.     # Process options
  618.     debug = 1
  619.     domods = 0
  620.     addpath = []
  621.     exclude = []
  622.     for o, a in opts:
  623.         if o == '-d':
  624.             debug = debug + 1
  625.         if o == '-m':
  626.             domods = 1
  627.         if o == '-p':
  628.             addpath = addpath + a.split(os.pathsep)
  629.         if o == '-q':
  630.             debug = 0
  631.         if o == '-x':
  632.             exclude.append(a)
  633.  
  634.     # Provide default arguments
  635.     if not args:
  636.         script = "hello.py"
  637.     else:
  638.         script = args[0]
  639.  
  640.     # Set the path based on sys.path and the script directory
  641.     path = sys.path[:]
  642.     path[0] = os.path.dirname(script)
  643.     path = addpath + path
  644.     if debug > 1:
  645.         print "path:"
  646.         for item in path:
  647.             print "   ", repr(item)
  648.  
  649.     # Create the module finder and turn its crank
  650.     mf = ModuleFinder(path, debug, exclude)
  651.     for arg in args[1:]:
  652.         if arg == '-m':
  653.             domods = 1
  654.             continue
  655.         if domods:
  656.             if arg[-2:] == '.*':
  657.                 mf.import_hook(arg[:-2], None, ["*"])
  658.             else:
  659.                 mf.import_hook(arg)
  660.         else:
  661.             mf.load_file(arg)
  662.     mf.run_script(script)
  663.     mf.report()
  664.     return mf  # for -i debugging
  665.  
  666.  
  667. if __name__ == '__main__':
  668.     try:
  669.         mf = test()
  670.     except KeyboardInterrupt:
  671.         print "\n[interrupt]"
  672.